#!/bin/sh
# shellcheck shell=dash disable=SC2169,SC2153,SC3010 source=/dev/null
#
# startup script that updates HomeMatic-RF devices, if necessary.
#

update_rf_hardware() {

  if [[ ! -r /etc/config/force-no-coprocessor-update ]]; then
    FOUND=0

    ARCH=$(uname -m)
    JAVAOPT=

    # check if user has a HM-MOD-RPI-PCB installed (GPIO) and
    # perform a firmware update if necessary
    if [[ "${HM_HMRF_DEV}" == "HM-MOD-RPI-PCB" ]] ||
       [[ "${HM_HMIP_DEV}" == "HM-MOD-RPI-PCB" ]]; then

      echo -n "HM-MOD-RPI-PCB: "

      FW_DIRECTORY=/firmware/HM-MOD-UART

      # identify which firmware file to take for a potential coprocessor
      # firmware update
      FORCED_VERSION=
      if [[ ! -s /etc/config/forced_coprocessor_version ]]; then
        FW_FILE=dualcopro_si1002_update_blhm.eq3
      else
        FORCED_VERSION=$(cat /etc/config/forced_coprocessor_version)
        NEW_VERSION=${FORCED_VERSION}
        FW_FILE="dualcopro_si1002_update_blhm-${FORCED_VERSION}.eq3"
      fi

      # identify the copro firmware version to be flashed
      if [[ -z "${NEW_VERSION}" ]]; then
        NEW_VERSION=$(grep "${FW_FILE}" "${FW_DIRECTORY}/fwmap" | awk '{ print $3 }')
      fi

      # get OLD_VERSION from var tmp file
      if [[ "${HM_HMRF_DEV}" == "HM-MOD-RPI-PCB" ]]; then
        OLD_VERSION=$(cat /var/rf_firmware_version 2>/dev/null)
      else
        OLD_VERSION=$(cat /var/hmip_firmware_version 2>/dev/null)
      fi

      # if NEW_VERSION is not empty we go ahead and perform the
      # update operation
      if [[ -n "${NEW_VERSION}" ]] && [[ "${NEW_VERSION}" != "${OLD_VERSION}" ]]; then
        # we always perform the firmware update in /tmp
        # so lets copy the whole firmware directory to tmp
        TMPDIR_FW=$(mktemp -d)
        cp -a "${FW_DIRECTORY}/${FW_FILE}" "${TMPDIR_FW}"

        # create artifical fwmap file
        echo "CCU2 ${FW_FILE} ${NEW_VERSION}" >"${TMPDIR_FW}/fwmap"

        if [[ "${HM_HMRF_DEV}" == "HM-MOD-RPI-PCB" ]] && [[ -n "${HM_HMRF_DEVNODE}" ]]; then
          DEVNODE=${HM_HMRF_DEVNODE}
        elif [[ "${HM_HMIP_DEV}" == "HM-MOD-RPI-PCB" ]] && [[ -n "${HM_HMIP_DEVNODE}" ]]; then
          DEVNODE=${HM_HMIP_DEVNODE}
        fi

        echo -n "${OLD_VERSION}=>${NEW_VERSION}"
        if [[ -n "${FORCED_VERSION}" ]]; then
          echo -n " (forced), "
        else
          echo -n ", "
        fi

        # perform the coprocessor update
        if ! /usr/bin/timeout 120 /bin/eq3configcmd update-coprocessor -p "${DEVNODE}" -t HM-MOD-UART -u -d "${TMPDIR_FW}"; then
          echo -n "repeat, "
          /usr/bin/timeout 240 /bin/eq3configcmd update-coprocessor -p "${DEVNODE}" -t HM-MOD-UART -u -f -d "${TMPDIR_FW}"
        fi
        HM_HMRF_VERSION=$(/usr/bin/timeout 30 /bin/eq3configcmd update-coprocessor -p "${DEVNODE}" -t HM-MOD-UART -c -v 2>&1 | grep "Version:" | cut -d' ' -f5)

        echo "${HM_HMRF_VERSION}" >/var/rf_firmware_version
        if [[ "${HM_HMRF_DEVNODE}" == "${HM_HMIP_DEVNODE}" ]]; then
          HM_HMIP_VERSION=${HM_HMRF_VERSION}
          echo "${HM_HMIP_VERSION}" >/var/hmip_firmware_version
        fi

        if [[ "${NEW_VERSION}" == "${HM_HMRF_VERSION}" ]]; then
          echo -n "OK"
        else
          echo -n "ERROR (${HM_HMRF_VERSION} != ${NEW_VERSION})"
        fi

        # remove the temporary directory again
        rm -rf "${TMPDIR_FW}"
      else
        echo -n "${OLD_VERSION}"
        if [[ -n "${FORCED_VERSION}" ]]; then
          echo -n " (forced)"
        fi
        echo -n ", not necessary, OK"
      fi
      FOUND=1
    fi

    # check if user has a RPI-RF-MOD installed (GPIO) and
    # perform a firmware update if necessary
    if [[ "${HM_HMRF_DEV}" == "RPI-RF-MOD" ]] ||
       [[ "${HM_HMIP_DEV}" == "RPI-RF-MOD" ]]; then

      if [[ ${FOUND} -eq 1 ]]; then
        echo -n "; "
      fi

      echo -n "RPI-RF-MOD: "

      FORCED_VERSION=
      if [[ -s /etc/config/forced_coprocessor_version ]]; then
        FORCED_VERSION=$(cat /etc/config/forced_coprocessor_version)
      fi

      LATEST_FIRMWARE=$(find /firmware/RPI-RF-MOD -name "dualcopro_update_blhmip-*.eq3" -maxdepth 1 | grep "${FORCED_VERSION}" | sort -V | tail -1)
      NEW_VERSION=$(echo "${LATEST_FIRMWARE}" | sed 's/.*-\(.*\)\.eq3/\1/')

      # get OLD_VERSION from var tmp file
      if [[ "${HM_HMRF_DEV}" == "RPI-RF-MOD" ]]; then
        OLD_VERSION=$(cat /var/rf_firmware_version 2>/dev/null)
        DEVNODE=${HM_HMRF_DEVNODE}
      else
        OLD_VERSION=$(cat /var/hmip_firmware_version 2>/dev/null)
        DEVNODE=${HM_HMIP_DEVNODE}
      fi

      # if NEW_VERSION is not empty we go ahead and perform the
      # update operation
      if [[ "${NEW_VERSION}" != "${OLD_VERSION}" ]]; then
        echo -n "${OLD_VERSION}=>${NEW_VERSION}"
        if [[ -n "${FORCED_VERSION}" ]]; then
          echo -n " (forced), "
        else
          echo -n ", "
        fi

        # run firmware update
        # shellcheck disable=SC2086
        /usr/bin/timeout 120 /opt/java/bin/java -Dos.arch=${ARCH} ${JAVAOPT} -Dgnu.io.rxtx.SerialPorts="${DEVNODE}" -jar /opt/HmIP/hmip-copro-update.jar -p "${DEVNODE}" -o -f "${LATEST_FIRMWARE}" 2>/dev/null >/dev/null

        # verify new firmware version
        sleep 1 # give copro app some time to startup
        HM_HMIP_VERSION=$(/bin/detect_radio_module "${DEVNODE}" | cut -d' ' -f6)

        echo "${HM_HMIP_VERSION}" >/var/hmip_firmware_version
        if [[ "${HM_HMRF_DEVNODE}" == "${HM_HMIP_DEVNODE}" ]]; then
          HM_HMRF_VERSION=${HM_HMIP_VERSION}
          echo "${HM_HMRF_VERSION}" >/var/rf_firmware_version
        fi

        if [[ "${NEW_VERSION}" == "${HM_HMIP_VERSION}" ]]; then
          echo -n "OK"
        else
          echo -n "ERROR (${HM_HMIP_VERSION} != ${NEW_VERSION})"
        fi
      else
        echo -n "${OLD_VERSION}"
        if [[ -n "${FORCED_VERSION}" ]]; then
          echo -n " (forced)"
        fi
        echo -n ", not necessary, OK"
      fi

      FOUND=1
    fi

    # check if user has a HMIP-RFUSB-TK (Telekom) installed (USB)
    # for which we don't supply any firmware updates
    if [[ "${HM_HMIP_DEV}" == "HMIP-RFUSB-TK" ]]; then
      if [[ ${FOUND} -eq 1 ]]; then
        echo -n "; "
      fi
      echo -n "HMIP-RFUSB-TK: ${HM_HMIP_VERSION}, not necessary, OK"

      FOUND=1

    # check if user has a HMIP-RFUSB (eQ3) installed (USB)
    # for which we supply recent firmware updates
    elif [[ "${HM_HMRF_DEV}" == "HMIP-RFUSB" ]] ||
         [[ "${HM_HMIP_DEV}" == "HMIP-RFUSB" ]] ||
         lsusb 2>/dev/null | grep -q 1b1f:c020; then

      if [[ ${FOUND} -eq 1 ]]; then
        echo -n "; "
      fi

      echo -n "HMIP-RFUSB: "

      FORCED_VERSION=
      if [[ -s /etc/config/forced_coprocessor_version ]]; then
        FORCED_VERSION=$(cat /etc/config/forced_coprocessor_version)
      fi

      # check for new firmware file in /firmware/HmIP-RFUSB
      LATEST_FIRMWARE=$(find /firmware/HmIP-RFUSB -name "dualcopro_update_blhmip-*.eq3" -maxdepth 1 | grep "${FORCED_VERSION}" |  sort -V | tail -1)
      NEW_VERSION=$(echo "${LATEST_FIRMWARE}" | sed 's/.*-\(.*\)\.eq3/\1/')

      # get OLD_VERSION from var tmp file
      if [[ "${HM_HMRF_DEV}" == "HMIP-RFUSB" ]]; then
        OLD_VERSION=$(cat /var/rf_firmware_version 2>/dev/null)
        DEVNODE=${HM_HMRF_DEVNODE}
      else
        OLD_VERSION=$(cat /var/hmip_firmware_version 2>/dev/null)
        DEVNODE=${HM_HMIP_DEVNODE}
      fi

      # if DEVNODE is empty the stick seems to carry an invalid
      # firmware, thus we have to force flash the latest one
      if [[ -z "${DEVNODE}" ]]; then
        # find out which raw-uart node the RFUSB belongs to
        for n in $(seq 0 9); do
          if [[ $n -eq 0 ]]; then n=""; fi
          if grep -q "HmIP-RFUSB@" "/sys/class/raw-uart/raw-uart${n}/device_type" 2>/dev/null; then
            DEVNODE=/dev/raw-uart${n}
            REINIT=yes
            break
          fi
        done
      fi

      # if NEW_VERSION is not empty we go ahead and perform the
      # update operation
      if [[ "${NEW_VERSION}" != "${OLD_VERSION}" ]]; then
        echo -n "${OLD_VERSION}=>${NEW_VERSION}"
        if [[ -n "${FORCED_VERSION}" ]]; then
          echo -n " (forced), "
        else
          echo -n ", "
        fi

        # run firmware update
        # shellcheck disable=SC2086
        /usr/bin/timeout 120 /opt/java/bin/java -Dos.arch=${ARCH} ${JAVAOPT} -Dgnu.io.rxtx.SerialPorts="${DEVNODE}" -jar /opt/HmIP/hmip-copro-update.jar -p "${DEVNODE}" -o -f "${LATEST_FIRMWARE}" 2>/dev/null >/dev/null

        # verify new firmware version
        sleep 1 # give copro app some time to startup
        HM_HMIP_VERSION=$(/bin/detect_radio_module "${DEVNODE}" | cut -d' ' -f6)

        echo "${HM_HMIP_VERSION}" >/var/hmip_firmware_version
        if [[ "${HM_HMRF_DEVNODE}" == "${HM_HMIP_DEVNODE}" ]]; then
          HM_HMRF_VERSION=${HM_HMIP_VERSION}
          echo "${HM_HMRF_VERSION}" >/var/rf_firmware_version
        fi

        if [[ "${NEW_VERSION}" == "${HM_HMIP_VERSION}" ]]; then
          echo -n "OK"
        else
          echo -n "ERROR (${HM_HMIP_VERSION} != ${NEW_VERSION})"
        fi
      else
        echo -n "${OLD_VERSION}"
        if [[ -n "${FORCED_VERSION}" ]]; then
          echo -n " (forced)"
        fi
        echo -n ", not necessary, OK"
      fi

      FOUND=1
    fi

    if [[ ${FOUND} -eq 0 ]]; then
      echo "no GPIO/USB connected RF-hardware found"
    else
      # final echo
      echo
    fi
  else
    echo "disabled"
  fi
}

start() {
  echo -n "Updating Homematic RF-Hardware: "

  # source all data from /var/hm_mode
  [[ -r /var/hm_mode ]] && . /var/hm_mode

  # check+update rf module firmwares
  update_rf_hardware

  # save all HM_ env variables
  set | grep '^HM_' >/var/hm_mode

  # check if we should re-init afterwards
  if [[ -n "${REINIT}" ]]; then
    /etc/init.d/S47InitRFHardware start
  fi
}

case "$1" in
  start)
    start
  ;;
  stop)
    # nothing
  ;;
  *)
    echo "Usage: $0 {start}"
    exit 1
esac

exit 0
